package offical.baseClass

/**
 * 类，类属性，类方法默认都是final ，不可以继承和重写
 * 子类需要复写和继承都需要加上open 关键字
 */
open class Father(open val id: Int, open val name: String) {
    open fun test() {
        println("Inter am Father")
    }
}

/**
 * 可以用一个 var 属性覆盖一个 val 属性，但反之则不行。
 * 因为一个 val 属性本质上声明了一个 getter 方法，而将其覆盖为 var 只是在子类中额外声明一个 setter 方法。
 */
open class Children(override var id: Int, name: String) : Father(id, name) {

    /**
     * 子类覆盖父类属性
     */
    override val name: String
        get() = "childrenName"

    /**
     * 标记为 override 的成员本身是开放的，也就是说，它可以在子类中覆盖
     */
    override fun test() {
        println("Inter am Children")
    }
}

class GrandSon(id: Int, name: String) : Children(id, name) {


    override fun test() {
        println("Inter am GrandSon")
    }
}


open class View(ctx: Int) {

    constructor(ctx: Int, attrs: String) : this(ctx)
}

/**
 * 如果类没有主构造函数，那么每个次构造函数必须使用 super 关键字初始化其基类型，或委托给另一个构造函数做到这一点。
 * 注意，在这种情况下，不同的次构造函数可以调用基类型的不同的构造函数：
 */
class MvView : View {

    constructor(ctx: Int) : super(ctx)

    constructor(ctx: Int, attrs: String) : super(ctx, attrs)

}

/**
 * 设计一个基类时，应该避免在构造函数、属性初始化器以及 init 块中使用 open 成员
 */
open class BaseInit(private val name: String) {

    init {
        //2
        println("init Base $name")
    }

    open val size: Int = name.length.also {
        //3
        println("init size in Base $it")
        it + 10  //并不会有改变，原值返回
    }
}

class ChildInit(name: String, private val lastName: String) : BaseInit(
        //1
        name.capitalize().also { println("argument for Base $it") }
) {

    init {
        //4
        println("init child ")
    }

    override val size: Int
    //5
        get() = (super.size + lastName.length).also { println("size argument for child $it") }

}


open class Foo(val age: Int = 1) {
    open fun f() {
        println("f...")
    }
}

class Bar : Foo() {
    override fun f() {
        println("f...${super.age}")
    }

    /**
     * 在一个内部类中访问外部类的超类，可以通过由外部类名限定的 super 关键字来实现：super@Outer
     */
    inner class Baz {
        fun g() {
            f()
            super@Bar.f()
        }
    }
}

abstract class AbstraParent {
    abstract fun a()
}

interface Inter {
    fun a() = println("Inter")
}

class Iml : AbstraParent(), Inter {
    override fun a() {
        super<Inter>.a()
    }
}

fun main(args: Array<String>) {
    val father: Father = Children(1, "67373")
    println(father.name)

    val c: BaseInit = ChildInit("陈一发", "陈")
    println(c.size)//输出4

    val b = BaseInit("女流")
    println(b.size)

    Bar().Baz().g()

}

